package main

import (
	"apis/global"
	"apis/initialize"
	"apis/utils"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"go.uber.org/zap"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"net/http"
	"regexp"

	//自主封装的远程包
	"gitee.com/yumo01/bag/pb"
)

func init() {
	zap.S().Info("正在初始化配置文件")
	initialize.Zap()
	initialize.Viper()
	zap.S().Info("配置文件初始化完成")
}

// 这是gin框架客户端--即api端

func main() {
	r := gin.Default()
	//绑定视图层
	r.LoadHTMLGlob("views/*")
	//绑定静态文件服务
	r.Static("/static", "static")

	//请求grpc服务
	conn, err := grpc.Dial("localhost:8080", grpc.WithInsecure())
	if err != nil {
		zap.S().Error("创建grpc连接失败", err)
		return
	}
	defer conn.Close()

	//生成grpc客户端
	client := pb.NewUserClient(conn)

	//测试
	r.POST("/ping", func(c *gin.Context) {
		ping := c.PostForm("ping")
		res, err := client.Ping(context.Background(), &pb.Request{
			Ping: ping,
		})
		if err != nil {
			zap.S().Error("调用grpc服务中ping方法失败", err)
			c.JSON(500, gin.H{
				"error": err.Error(),
			})
			return
		}

		c.JSON(200, gin.H{
			"message": res.Pong,
		})
	})

	//用户注册
	r.POST("user/register", func(c *gin.Context) {
		username := c.PostForm("username")
		password1 := c.PostForm("password1")
		password2 := c.PostForm("password2")
		email := c.PostForm("email")
		tel := c.PostForm("tel")

		if password1 != password2 {
			c.JSON(400, gin.H{
				"msg": "两次密码不一致",
			})
			return
		}

		// 创建一个新的验证器实例
		v := validator.New()

		// 注册自定义的手机号验证器
		err = v.RegisterValidation("mobile", func(fl validator.FieldLevel) bool {
			phone := fl.Field().String()

			// 使用go内置regexp包编译正则表达式
			re := regexp.MustCompile(`^1[3579]\d{9}$`)
			return re.MatchString(phone)

			//return len(phone) == 11 && phone[0] == '1' && (phone[1] == '3' || phone[1] == '5' || phone[1] == '7' || phone[1] == '8')
		})
		//注册翻译模版--当前不可用
		//err = v.RegisterTranslation("mobile", global.Trans, func(ut ut.Translator) error {
		//	return ut.Add("mobile", "该手机号无效", true)
		//}, func(ut ut.Translator, fe validator.FieldError) string {
		//	t, _ := ut.T("mobile", fe.Field())
		//	return t
		//})
		if err != nil {
			zap.S().Error("注册手机号验证器失败", err)
			return
		}

		var u = global.User{
			Name:     username,
			Password: password1,
			Email:    email,
			Mobile:   tel,
		}

		// 进行结构体字段的验证
		err = v.Struct(u)
		if err != nil {
			// 验证失败，输出错误信息
			for _, err := range err.(validator.ValidationErrors) {
				c.JSON(http.StatusOK, gin.H{
					"msg": err.Field() + "字段不合理",
				})
				return
			}
		}

		_, err := client.Register(context.Background(), &pb.RegisterRequest{
			U: &pb.Users{
				Username: username,
				Password: password1,
				Email:    email,
				Tel:      tel,
			},
		})
		if err != nil {
			zap.S().Error("调用grpc服务中注册方法失败", err)
			c.JSON(500, gin.H{
				"msg": "注册失败",
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"msg": "注册成功",
		})
	})

	//登录
	r.POST("user/login", func(c *gin.Context) {
		username := c.PostForm("username")
		password := c.PostForm("password")
		_, err := client.Login(context.Background(), &pb.LoginRequest{
			U: &pb.Users{
				Username: username,
				Password: password,
			},
		})
		if err != nil {
			zap.S().Error("调用grpc服务中login方法失败", err)
			return
		}

		//将token保存到cookie中
		//c.SetCookie("token", res.Token, 30*60, "/", "localhost", false, true)

		token := utils.CreatJwt(username)
		// 将 Token 存入响应头部
		c.Header("Authorization", "Bearer "+token)

		c.JSON(200, gin.H{
			"msg": "登录成功",
		})
	})

	//用户列表--当前只用于做token验证
	r.POST("user/list", func(c *gin.Context) {
		//token, err := c.Cookie("token")
		//if err != nil {
		//	c.JSON(400, gin.H{
		//		"err": err,
		//	})
		//}

		ok, _ := warrant(c)
		if ok != true {
			c.JSON(400, gin.H{
				"msg": "token鉴权失败",
			})
			return
		}

		res, err := client.UserList(context.Background(), &pb.UserListRequest{})
		if err != nil {
			c.JSON(400, gin.H{
				"msg": "调用grpc服务中list方法失败",
			})
			return
		}

		c.JSON(int(res.Code), gin.H{
			"msg": res.Msg,
		})
	})

	//退出登录
	r.POST("user/exit", func(c *gin.Context) {
		//SetCookie各参数的意义分别是:名称，值，存活时间，作用路径，作用域，是否只在 HTTPS 连接下发送该 cookie，指定浏览器是否可以通过 JavaScript 访问该 cookie
		c.SetCookie("", "", -1, "/", "localhost", false, true)
		c.JSON(200, "已成功退出登录")
	})

	//密码找回
	r.POST("user/forgot_password", func(c *gin.Context) {
		_, err := client.ForgotPassword(context.Background(), &pb.ForgotPasswordRequest{
			Tel:   c.PostForm("tel"),
			Email: c.PostForm("email"),
		})
		if err != nil {
			zap.S().Error("调用grpc服务中ForgotPassword方法失败", err)
			return
		}

		c.JSON(200, gin.H{
			"msg": "成功",
		})

	})

	//密码修改
	r.POST("user/reset_password", func(c *gin.Context) {
		ok, uname := warrant(c)
		if ok != true {
			c.JSON(400, gin.H{
				"msg": "token鉴权失败",
			})
			return
		}
		password := c.PostForm("password")
		_, err := client.ResetPassword(context.Background(), &pb.ResetPasswordRequest{
			Username: uname,
			Password: password,
		})
		if err != nil {
			zap.S().Error("调用grpc服务中ResetPassword方法失败", err)
			return
		}

		c.JSON(200, gin.H{
			"msg": "修改成功",
		})

	})

	//未配置路由的默认页面
	r.NoRoute(func(c *gin.Context) {
		c.HTML(http.StatusOK, "404.html", gin.H{})
	})

	r.Run(":8888")
}

// 权证
func warrant(c *gin.Context) (bool, string) {
	token := c.GetHeader("Authorization")
	ok, user := utils.ParseJwt(token)

	return ok, user
}
